/*!
   \file

   \brief
      File contains the main function that's called to start up Avion on Windows. It interfaces
      AvionEngine with the Windows OS.

   © 2011 Mark W. Gabby II

   This file is part of Rock Hunter.

   Rock Hunter is free software: you can redistribute it and/or modify it under the terms of the
   GNU General Public License as published by the Free Software Foundation, either version 3 of the
   License, or (at your option) any later version.

   Rock Hunter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
   even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   General Public License for more details.

   You should have received a copy of the GNU General Public License along with Rock Hunter.
   If not, see <http://www.gnu.org/licenses/>.
*/
#include "Platforms/AvionWin.hpp"

#include "Systems/AvionEngine/AvionEngine.hpp"
#include "Systems/Platform/Platform.hpp"

#include "Systems/Interfaces/PlatformInterface.hpp"

#include "PlatformTypesWin.hpp"
#include "WindowsWindow.hpp"

HANDLE gInstanceHandle;
int gCommandShow;

extern WinPFDataStruct gPFData;
/*!
   \brief
      Starts the Avion engine, with a window of the specified parameters.

   \param CreateAppEntityFunction
      Callback that creates the game's entity, the class that owns and does all game processing.
   \param InstanceHandle
      Windows bookkeeping.
   \param CommandShow
      Windows bookkeeping. (Information on how the window should appear)
   \param Name
      Name on the window.
   \param Caption
      Window caption.

   \param Settings
      Settings for the window being created. Set them yourself, or use GetScreenSettings.
*/
int AvionWin( tCreateAppEntityFunction CreateAppEntityFunction,
              HINSTANCE InstanceHandle, int CommandShow,
              const char * Name, const char * Caption,
              const ScreenSettings & Settings )
{
   gInstanceHandle = InstanceHandle;
   gCommandShow = CommandShow;

   // Error checking
   if ( Settings.PixelFormatIndex == kNullPixelFormatIndex )
   {
      MessageBox( NULL, "Invalid pixel format specified. Try updating your graphics card drivers.",
                  "No Pixel Format", MB_OK | MB_ICONERROR );
      return -1;
   }
   else if ( Settings.MonitorIndex == kNullMonitorIndex )
   {
      MessageBox( NULL, "Invalid monitor specified. Contact game support.", "Invalid Monitor",
                  MB_OK | MB_ICONERROR );

      return -1;
   }

   AvionEngine Engine( CreateAppEntityFunction );
   Engine.PreWindowInitialize();


   WindowsWindow * NewWindow = new WindowsWindow();
   gPFData.Windows.push_back( NewWindow );

   // Fullscreen if we're changing the screen mode, false otherwise
   const bool Fullscreen = Settings.ModeIndex != kNullScreenModeIndex;
   const bool WindowBorder = !Fullscreen;
   NewWindow->Initialize( WindowBorder, Settings.PixelFormatIndex,
                          Settings.Width, Settings.Height,
                          Settings.OffsetX, Settings.OffsetY,
                          Settings.FOVDegrees, Settings.AspectRatio,
                          Name, Caption );

   if ( Fullscreen )
   {
      pf::SetScreenMode( Settings.ModeIndex, Settings.MonitorIndex );
   }

   if ( !Engine.Initialize() )
   {
      Engine.Exit();
      return 1;
   }
   MSG Msg = { 0 };

   // Update engine
   // If Update returns false, we'll exit.
   while ( Engine.Update() )
   {
      // Normal non-blocking message loop:
      // Peek and see if there's a message.
      if ( PeekMessage( &Msg, NULL, 0, 0, PM_REMOVE ) )
      {
         // If so, then translate the message
         TranslateMessage( &Msg );

         // If it's a quit message, then break out of this loop.
         if ( Msg.message == WM_QUIT )
         {
            break;
         }

         // Otherwise, dispatch the message.
         DispatchMessage( &Msg );
      }
   }

   Engine.Exit();

   return int( Msg.wParam );
}

int AvionWin( tCreateAppEntityFunction CreateAppEntityFunction,
              HINSTANCE InstanceHandle, int CommandShow,
              const char * Name, const char * Caption )
{
   ScreenSettings Settings = iPlatform::GetScreenSettings();

   return AvionWin( CreateAppEntityFunction, InstanceHandle, CommandShow, Name, Caption, Settings );
}
